<?php
/**
* 逻辑类的 基类
* author:wena
* 时间：2011-05-05
*/

class modelBase
{
	/**
	* 基类的构造函数
	*/
	/*private $msg_rule = array('notnull'=>'不能为空',//'不能为空',
	                          'maxlength'=>'字符长度不能超过',
							  'minlength'=>'字符长度不低于',
							  'equalto'=>'2次密码输入不一致',
							  'email'=>'格式不正确');*/
	public function __construct()
	{
	}
	
	/**
	* 获取参数值
	* @param name 参数键值
	*/
	public function getArgs($name)
	{
		 
		if($name)
		{
			if($_REQUEST[$name])
			{
				$_REQUEST[$name]=trim($_REQUEST[$name]);
				if(!QUOTESGPS){
					$_REQUEST[$name]=addslashes($_REQUEST[$name]);
				}
				return $_REQUEST[$name];
				//return addslashes(trim($_REQUEST[$name]));
			}else{
				return NULL;
			}
		}else{
			throw new Exception('参数不能为空！');
		}
	}
	/**
	*字段验证
	*@param filed 待验证的表单，规则
	*        字段名        验证规则   验证规则         规则的第2个参数
	* array('key'=>array('notnull','equalto'=>array($this->getArgs('pw')))))
	*/
	public function validate($filed=array(),$arrname =array())
	{
		$v_flag = true;
		$rule ='';
		foreach($filed as $key=>$vals)
		{
			foreach($vals as $k=>$v)
			{
				//验证规则的参数是数组，则存在第2个参数
				if(is_array($v))
				{
					$v_flag = $this->$k(stripslashes($this->getArgs($key)),$v[0]);//调用验证规则
					if($k!='equalto')
					$args=$v[0];
					else
					$args='';
					$rule=$k;
				}else
				{
					$v_flag = $this->$v(stripslashes($this->getArgs($key)),true);//调用验证规则
					$rule=$v;
				}
				if(!$v_flag)
				{
					return $arrname[$key].$GLOBALS['TS'][$rule].$args;
				}
			}
		}
		return '';
	}
	
	private function notnull($val, $right){return $right === ( strlen($val) > 0 );}
	/** 
	 * 内置验证器，检查字符串是否小于指定长度
	 * @param val    待验证字符串
	 * @param right    正确值
	 */
	private function minlength($val, $right){return $this->cn_strlen($val) >= $right;}
	/** 
	 * 内置验证器，检查字符串是否大于指定长度
	 * @param val    待验证字符串
	 * @param right    正确值
	 */
	private function maxlength($val, $right){return $this->cn_strlen($val) <= $right;}
	/** 
	 * 内置验证器，检查字符串是否等于另一个验证字段的值
	 * @param val    待验证字符串
	 * @param right    正确值
	 */
	private function equalto($val, $right){return $val == $right;}
	/** 
	 * 内置验证器，检查字符串是否正确的时间格式
	 * @param val    待验证字符串
	 * @param right    正确值
	 */
	private function istime($val, $right){$test = @strtotime($val);return $right == ( $test !== -1 && $test !== false );}
	/** 
	 * 内置验证器，检查字符串是否正确的电子邮件格式
	 * @param val    待验证字符串
	 * @param right    正确值
	 */	
	private function email($val, $right){
		return $right == ( preg_match('/^[A-Za-z0-9]+([._\-\+]*[A-Za-z0-9]+)*@([A-Za-z0-9-]+\.)+[A-Za-z0-9]+$/', $val) != 0 );
	}
	
	/** 
	 * 计算字符串长度，支持包括汉字在内的字符串
	 * @param val    待计算的字符串
	 */
	public function cn_strlen($val){$i=0;$n=0;
		while($i<strlen($val)){$clen = ( strlen("我靠") == 4 ) ? 2 : 3;
			if(preg_match("/^[".chr(0xa1)."-".chr(0xff)."]+$/",$val[$i])){$i+=$clen;}else{$i+=1;}$n+=1;}
		return $n;
	}
	
	
    /**
     * 获得访问者的ip地址
     * @return string $ip
     */
	public static function getip(){
		if(isset($_SERVER)){
			if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
				$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
			}elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
				$ip = $_SERVER['HTTP_CLIENT_IP'];
			}else{
				$ip = $_SERVER['REMOTE_ADDR'];
			}	
		}else{
			if(getenv('HTTP_X_FORWARDED_FOR')){
				$ip = getenv('HTTP_X_FORWARDED_FOR');
			}elseif(getenv('HTTP_CLIENT_IP')){
				$ip = getenv('HTTP_CLIENT_IP');
			}else{
				$ip = getenv('REMOTE_ADDR');
			}
		}
		return $ip;
	}
	
	/**
	 * 初始化表单希哈码
     * @param string $key 表单希哈码键名
     * @return string
	 */
	static function formhash($key = ''){
		if(empty($key)){
			$key = 'default';
		}
		return $_SESSION['formhash'][$key] = md5(time().self::getip().mt_rand());
	}
	
	/**
	 * 检测表单希哈码
     * @param string $val 表单希哈码
     * @param string $key 表单希哈码键名
     * @return bool(true|false)
	 */
	static function check_formhash($val, $key = ''){
		if(empty($val)) return false;
		if(empty($key)) $key = 'default';
		$res = $_SESSION['formhash'][$key] === $val;
		unset($_SESSION['formhash'][$key]);
		return $res;
	}
	
	/**
	 * 使用反斜线引用字符串,防止SQL注入
     * @param string $str 提交的参数
     * @return string $str
	 */
	static function check_data($str){
		if(!get_magic_quotes_gpc()){
			if(is_array($str)) foreach($str as $key => $val) $str[$key] = stripslashes($val);
			else $str = stripslashes($str);
		}
		return $str;
	}
	
	/**
	 * 危险html转义
     * @param string $str 提交的参数
     * @return string $str
	 */
	static function filter_html($str){
		return preg_replace(array(
				'/<(\/?)(script|i?frame|style|html|body|title|link|meta|object|param|embed|\?|\%)([^>]*?)>/isU',
				'/\s+/', '/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU',
				), array('\1\2', ' ', '',), $str);
	}
	
	/**
	 * html转义
     * @param string $str 提交的参数
     * @return string $str
	 */
	static function special_html($str){
		if(is_array($str)) foreach($str as $key => $val) $str[$key] = htmlspecialchars($val);
		else $str = htmlspecialchars($str);	
		return $str;
	}
	
	/**
	 * html反转义转义
     * @param string $str 提交的参数
     * @return string $str
	 */
	static function special_html_decode($str){
		if(is_array($str)) foreach($str as $key => $val) $str[$key] = htmlspecialchars_decode($val);
		else $str = htmlspecialchars_decode($str);	
		return $str;
	}
	
	/**
	 * 防刷新,防cc,基于session
     * @param int $timestamp 时间间隔
     * @param int $num 间隔内的刷新次数
     * @return bool(true|false)
	 */
	static function anticc($timestamp=10,$num=5){
		$nowtime = time();
		$cc_lasttime = $_SESSION['cc_lasttime'];
		$cc_num = $_SESSION['cc_num'];
		if($cc_lasttime){
			if($nowtime <= ($cc_lasttime+$timestamp)){
				if($cc_num >= $num){
					//exit('你刷新太快了');
					return false;
				}else{
					$_SESSION['cc_num'] += 1;
				}
			}else{
				$_SESSION['cc_lasttime'] = $nowtime;
				$_SESSION['cc_num'] = 1;
			}
		}else{
			$_SESSION['cc_lasttime'] = $nowtime;
			$_SESSION['cc_num'] = 1;
		}
		return true;
	}
	
	/**
	 * 根据IP获取访问者的地址
     * @param string $ip ip地址
     * @return string
	 */
	static function convertip($ip){
		$return = '';
		if(preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
			$iparray = explode('.', $ip);
			if($iparray[0] == 10 || $iparray[0] == 127 || ($iparray[0] == 192 && $iparray[1] == 168) || ($iparray[0] == 172 && ($iparray[1] >= 16 && $iparray[1] <= 31))) {
				//$return = '- LAN';
				$return = 'false';
			} elseif($iparray[0] > 255 || $iparray[1] > 255 || $iparray[2] > 255 || $iparray[3] > 255) {
				//$return = '- Invalid IP Address';
				$return = 'false';
			} else {
				//$tinyipfile = ROOT_PATH . 'tpl\yitu\Public\ip\ip.dat';
				$fullipfile = ROOT_PATH . 'tpl\yitu\Public\ip\ip.dat';
				if(@file_exists($tinyipfile)) {
					$return = self::convertip_tiny($ip, $tinyipfile);
				} elseif(@file_exists($fullipfile)) {
					$return = self::convertip_full($ip, $fullipfile);
				}
			}
		}
		return $return;
	}
	
	/**
	 * tiny型IP地址库读取
     * @param string $ip ip地址
     * @param string $ipdatafile 文件地址
     * @return string
	 */
	static function convertip_tiny($ip, $ipdatafile){
		static $fp = NULL, $offset = array(), $index = NULL;
		$ipdot = explode('.', $ip);
		$ip    = pack('N', ip2long($ip));
		$ipdot[0] = (int)$ipdot[0];
		$ipdot[1] = (int)$ipdot[1];
		if($fp === NULL && $fp = @fopen($ipdatafile, 'rb')){
			$offset = @unpack('Nlen', @fread($fp, 4));
			$index  = @fread($fp, $offset['len'] - 4);
		} elseif($fp == FALSE) {
			//return  '- Invalid IP data file';
			return 'false';
		}
		$length = $offset['len'] - 1028;
		$start  = @unpack('Vlen', $index[$ipdot[0] * 4] . $index[$ipdot[0] * 4 + 1] . $index[$ipdot[0] * 4 + 2] . $index[$ipdot[0] * 4 + 3]);
	
		for($start = $start['len'] * 8 + 1024; $start < $length; $start += 8){
	
			if($index{$start} . $index{$start + 1} . $index{$start + 2} . $index{$start + 3} >= $ip){
				$index_offset = @unpack('Vlen', $index{$start + 4} . $index{$start + 5} . $index{$start + 6} . "\x0");
				$index_length = @unpack('Clen', $index{$start + 7});
				break;
			}
		}
		@fseek($fp, $offset['len'] + $index_offset['len'] - 1024);
		if($index_length['len']){
			return '- '.@fread($fp, $index_length['len']);
		}else{
			//return '- Unknown';
			return 'false';
		}
	}
	
	/**
	 * full型IP地址库读取
     * @param string $ip ip地址
     * @param string $ipdatafile 文件地址
     * @return string
	 */
	static function convertip_full($ip, $ipdatafile){
		if(!$fd = @fopen($ipdatafile, 'rb')){
			//return '- Invalid IP data file';
			return 'false';
		}
		$ip = explode('.', $ip);
		$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
		if(!($DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4)) ) return;
		@$ipbegin = implode('', unpack('L', $DataBegin));
		if($ipbegin < 0) $ipbegin += pow(2, 32);
		@$ipend = implode('', unpack('L', $DataEnd));
		if($ipend < 0) $ipend += pow(2, 32);
		$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
		$BeginNum = $ip2num = $ip1num = 0;
		$ipAddr1 = $ipAddr2 = '';
		$EndNum = $ipAllNum;
		while($ip1num > $ipNum || $ip2num < $ipNum) {
			$Middle= intval(($EndNum + $BeginNum) / 2);
	
			fseek($fd, $ipbegin + 7 * $Middle);
			$ipData1 = fread($fd, 4);
			if(strlen($ipData1) < 4) {
				fclose($fd);
				//return '- System Error';
				return 'false';
			}
			$ip1num = implode('', unpack('L', $ipData1));
			if($ip1num < 0) $ip1num += pow(2, 32);
	
			if($ip1num > $ipNum) {
				$EndNum = $Middle;
				continue;
			}
	
			$DataSeek = fread($fd, 3);
			if(strlen($DataSeek) < 3) {
				fclose($fd);
				//return '- System Error';
				return 'false';
			}
			$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
			fseek($fd, $DataSeek);
			$ipData2 = fread($fd, 4);
			if(strlen($ipData2) < 4) {
				fclose($fd);
				//return '- System Error';
				return 'false';
			}
			$ip2num = implode('', unpack('L', $ipData2));
			if($ip2num < 0) $ip2num += pow(2, 32);
	
			if($ip2num < $ipNum) {
				if($Middle == $BeginNum) {
					fclose($fd);
					//return '- Unknown';
					return 'false';
				}
				$BeginNum = $Middle;
			}
		}
	
		$ipFlag = fread($fd, 1);
		if($ipFlag == chr(1)) {
			$ipSeek = fread($fd, 3);
			if(strlen($ipSeek) < 3) {
				fclose($fd);
				//return '- System Error';
				return 'false';
			}
			$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
			fseek($fd, $ipSeek);
			$ipFlag = fread($fd, 1);
		}
	
		if($ipFlag == chr(2)) {
			$AddrSeek = fread($fd, 3);
			if(strlen($AddrSeek) < 3) {
				fclose($fd);
				//return '- System Error';
				return 'false';
			}
			$ipFlag = fread($fd, 1);
			if($ipFlag == chr(2)) {
				$AddrSeek2 = fread($fd, 3);
				if(strlen($AddrSeek2) < 3) {
					fclose($fd);
					//return '- System Error';
					return 'false';
				}
				$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
				fseek($fd, $AddrSeek2);
			} else {
				fseek($fd, -1, SEEK_CUR);
			}
	
			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr2 .= $char;
	
			$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
			fseek($fd, $AddrSeek);
	
			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr1 .= $char;
		} else {
			fseek($fd, -1, SEEK_CUR);
			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr1 .= $char;
	
			$ipFlag = fread($fd, 1);
			if($ipFlag == chr(2)) {
				$AddrSeek2 = fread($fd, 3);
				if(strlen($AddrSeek2) < 3) {
					fclose($fd);
					//return '- System Error';
					return 'false';
				}
				$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
				fseek($fd, $AddrSeek2);
			} else {
				fseek($fd, -1, SEEK_CUR);
			}
			while(($char = fread($fd, 1)) != chr(0))
			$ipAddr2 .= $char;
		}
		fclose($fd);
	
		if(preg_match('/http/i', $ipAddr2)) {
			$ipAddr2 = '';
		}
		$ipaddr = "$ipAddr1 $ipAddr2";
		$ipaddr = preg_replace('/CZ88\.NET/is', '', $ipaddr);
		$ipaddr = preg_replace('/^\s*/is', '', $ipaddr);
		$ipaddr = preg_replace('/\s*$/is', '', $ipaddr);
		if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
			//$ipaddr = '- Unknown';
			return 'false';
		}
		return '- '.$ipaddr;
	}
	
	//字符串解密加密
 	static function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
  
	  $ckey_length = 8;	// 随机密钥长度 取值 0-32;
				  // 加入随机密钥，可以令密文无任何规律，即便是原文和密钥完全相同，加密结果也会每次不同，增大破解难度。
				  // 取值越大，密文变动规律越大，密文变化 = 16 的 $ckey_length 次方
				  // 当此值为 0 时，则不产生随机密钥
  
	  $key = md5($key ? $key : 'yitu');
	  $keya = md5(substr($key, 0, 16));
	  $keyb = md5(substr($key, 16, 16));
	  $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
  
	  $cryptkey = $keya.md5($keya.$keyc);
	  $key_length = strlen($cryptkey);
  
	  $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
	  $string_length = strlen($string);
  
	  $result = '';
	  $box = range(0, 255);
  
	  $rndkey = array();
	  for($i = 0; $i <= 255; $i++) {
		  $rndkey[$i] = ord($cryptkey[$i % $key_length]);
	  }
  
	  for($j = $i = 0; $i < 256; $i++) {
		  $j = ($j + $box[$i] + $rndkey[$i]) % 256;
		  $tmp = $box[$i];
		  $box[$i] = $box[$j];
		  $box[$j] = $tmp;
	  }
  
	  for($a = $j = $i = 0; $i < $string_length; $i++) {
		  $a = ($a + 1) % 256;
		  $j = ($j + $box[$a]) % 256;
		  $tmp = $box[$a];
		  $box[$a] = $box[$j];
		  $box[$j] = $tmp;
		  $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
	  }
  
	  if($operation == 'DECODE') {
		  if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
			  return substr($result, 26);
		  } else {
			  return '';
		  }
	  } else {
		  return $keyc.str_replace('=', '', base64_encode($result));
	  }
  }
}
?>